/*
 * NameSpace.java
 * 
 * last update: 16.01.2010 by Stefan Saru
 * 
 * author:	Alec(panovici@elcom.pub.ro)
 * 
 * Obs:
 */

package engine;

import java.util.Hashtable;

/**
 * A symbol container. Its main task is name resolving:
 * the algoithm is :
 * 1. if a non-FQN (fully qualified name) is given, then it is resolved within
 *     the innermost module, by going up in the task/function/named block hierarcy.
 * 2. if the name has the form <module_instance_name>.<name>, then it is esolved
 *      as a downward reference:
 *   2.a. look in the curent module for a module instance named
 *        <module_instance_name>; if found, 
 *        <name> must be resolved within that instance
 *   2.b. look in the parent module of the current module for a module instance called 
 *        <module_instance_name>; if found, then <name> must be resolved within it
 *   2.c. repeat step 2.b, mobing up in the hierarcy
 * 3. try resolve the name starting with the 'top' modules
 * Note: because rule 2 and 3 can give birth to some confusions ( what if there
 *        are two modules with the same name, one at the top level and the
 *        other in the current's module branch, and a two-name identifier is
 *        given in the hope that it will refer to the top one ?) the use of a
 *        special name, "@top" is allowed in order to force the resolving
 *        process to start from the root of the hierarcy. Please note that
 *        "@top" is not a reserved name, but if used as a module name, any
 *        two-name identifier will refer to the root, not the user's "@top"
 *        module.
 *       
 */
class NameSpace
{

	/**
	 * The enclosing NameSpace of this NameSpace.
	 */
	NameSpace parent;
	Hashtable scopeData;

	/**
	 * Set it to false to prevent name resolver to pass non-fqn's to the parent
	 * if no match is found inside this namespace (so the name resolving of a 
	 * non-fqn won't pass the module border).
	 */
	boolean downwardAllowed;
	NameSpaceDescription desc;

	NameSpace (NameSpace parent, NameSpaceDescription desc) {
		this.desc = desc;
		this.parent = parent;
		downwardAllowed = true;
		scopeData = new Hashtable();
	}

	public Object resolveName(FQN fqn) {
		int l = fqn.len();
		if (l == 1) { //local ref
			Object o = scopeData.get((String) fqn.node);
			if (o == null && downwardAllowed) return parent.resolveName(fqn);
			else return o;
		} else {
			if (l == 2) { //downward reference
				Object o = scopeData.get((String) fqn.node);
				if(o != null)
					try {
						NameSpace n = (NameSpace)o;
						return n.resolveNameExact(fqn.next);
					} catch (ClassCastException cex) {
						return null;
					}
					else return parent.resolveName(fqn);
			} else {
				Object o = scopeData.get((String) fqn.node);
				if ((o != null) && (o instanceof NameSpace)){
					if (fqn.next == null) return null;
					return ((NameSpace) o).resolveNameExact(fqn.next);
				}
				return main.topModule.resolveNameExact(fqn);
			}
		}
	}

	/**
	 * Search for an exactly match inside this scope.
	 * Used by resolveName after the first part 
	 * of an fqn has been sucessfully found.
	 */
	public Object resolveNameExact(FQN fqn) {
		if (fqn.next == null)
			return scopeData.get((String)fqn.node);
		Object o = scopeData.get((String) fqn.node);
		if (o != null &&(o instanceof NameSpace)) {
			if (fqn.next == null) return null;
			return ((NameSpace)o).resolveNameExact(fqn.next);
		}
		return null;
	}

	public String toString(){
		return (parent == null ? "" : parent + ".") + desc.name();
	}
}









